<?php
/**
 * 日本の祝日
 * @author admin
 *
 */
class holiday
{
	/** 祝日保存ファイル名 %sは当該年 */
	const FILENAME_HOLIDAY = 'holiday%s.inf';
	/** 保存年ファイル名 */
	const FILENAME_SAVEYEAR = 'saveyear.inf';
	/** リアル祝日保存ファイルパス */
	protected $_realFileNameHoliday;
	/** リアル保存年ファイルパス */
	protected $_realFileNameSaveYear;
	/** 祝日情報 */
	protected $_holidayInfo;
	/**　対象年 */
	protected $_year;

	/**
	 * 動的な取得は年に一回
	 * 取得後年内は、保存したファイルから祝日を取得する
	 * @param string $getForce　強制取得フラグ
	 */
	public function __construct($year=FALSE, $getForce=FALSE)
	{
		/** 年が未設定の場合、今年を設定 */
		if ($year === FALSE) {
			$year = date('Y');
		}
		$this->_year = $year;

		$this->_realFileNameHoliday
		= dirname(__FILE__).'/'. sprintf(self::FILENAME_HOLIDAY, $year);
		$this->_realFileNameSaveYear = dirname(__FILE__). '/' . self::FILENAME_SAVEYEAR;
		/*** 強制取得要求が無くとも、状況に応じて取得を実施する。 */
		if ($getForce == FALSE) {
			/** 祝日保存ファイルがなければ強制作成 */
			if (!file_exists($this->_realFileNameHoliday)) {
				$getForce = TRUE;
			} else {
				// ファイルの更新日が今年でなければ強制作成
				if (date('Y',filemtime($this->_realFileNameHoliday)) != date('Y')) {
					$getForce = TRUE;
				} else {
					/** 保存年ファイルがなければ強制作成 */
					if (!file_exists($this->_realFileNameSaveYear)) {
						$getForce = TRUE;
					} else {
						$savedYear = file_get_contents($this->_realFileNameSaveYear);
						/** 保存年が今年でなければ強制作成 */
						if ($savedYear != date('Y')) {
							$getForce = TRUE;
						}
					}
				}
			}
		}

		/**
		 * ...で強制取得要求があれば取得してファイルに保存する
		 * なければ、ファイルから祝日情報を読み込む
		 */
		if ($getForce == TRUE) {
			$this->_holidayInfo = $this->getHolidays($year);
			$sHoliday = serialize($this->_holidayInfo);
			file_put_contents($this->_realFileNameHoliday, $sHoliday);
			file_put_contents($this->_realFileNameSaveYear, date('Y'));
		} else {
			$sHoliday = file_get_contents($this->_realFileNameHoliday);
			$this->_holidayInfo = unserialize($sHoliday);
		}
	}

	/**
	 * 祝日情報を外部ＡＰＩから取得する
	 * @return multitype:
	 */
	public function getHolidays($year)
	{
		$aryResult = array();
		$aryResult = $this->callGoogle($year);

		return $aryResult;
	}

	/**
	 * 指定年月日が祝日の場合ＴＲＵＥを返す
	 * @param unknown $year
	 * @param string $month
	 * @param string $day
	 * @return unknown
	 */
	public function isHoliday($year,$month='', $day='')
	{
		$result = FALSE;

		if (($month=='') && ($day=='')) {
			if (is_numeric($year)){
				if (strlen($year) != strlen('yyyymmdd')) {
					return FALSE;
				}
				$ymd = $year;
				$year = substr($ymd,0,4);
				$month = substr($ymd, 4,2);
				$day = substr($ymd, 6,2);
			} else {
				/*** 許容区切り文字 */
				$separators = array('-', '/', '.');
				foreach ($separators as $separator) {
					$divide = explode($separator, $year);
					if (count($divide) == 3) {
						break;
					}
				}
				if (count($divide) != 3) {
					return FALSE;
				}
				$year = $divide[0];
				$month = $divide[1];
				$day = $divide[2];
			}
		}

		$month = sprintf('%02d', $month);
		$day = sprintf('%02d', $day);
		$key = implode('-', array($year,$month,$day));

		if (isset($this->_holidayInfo[$key])) {
			$result = $this->_holidayInfo[$key];
		}

		return $result;
	}

	/**
	 * 祝日情報をＧＯＯＧＬＥＡＰＩから取得する
	 * @param string $year
	 * @return Ambigous <multitype:, multitype:string >
	 */
	public static function callGoogle($year=FALSE)
	{
		if ($year === FALSE) {
			$year = date('Y');
		}
		$aryResult = array();
		$holidays_url = sprintf(
				'http://www.google.com/calendar/feeds/%s/public/full-noattendees?start-min=%s&start-max=%s&max-results=%d&alt=json' ,
				'outid3el0qkcrsuf89fltf7a4qbacgt9@import.calendar.google.com' , // 'japanese@holiday.calendar.google.com' ,
				$year . '-01-01' ,  // 取得開始日
				$year . '-12-31' ,  // 取得終了日
				50              // 最大取得数
		);
		if ( $results = file_get_contents($holidays_url) ) {
			$results = json_decode($results, true);
			$holidays = array();
			foreach ($results['feed']['entry'] as $val ) {
				$date  = $val['gd$when'][0]['startTime'];
				$title = $val['title']['$t'];
				$divide = explode('/', $title);
				$title = trim($divide[0]);
				$holidays[$date] = $title;
			}
			ksort($holidays);
			$aryResult = $holidays;
		}
		return $aryResult;
	}
}

/**
 * 単体テストコードブロック
 */
if (PATH_SEPARATOR == ';') {
include_once 'simpletest/unit_tester.php';
include_once 'simpletest/reporter.php';

if (class_exists('UnitTestCase')) {
class HolidayTest extends UnitTestCase
{
	public function test1100()
	{
		//$b = new holiday();
//		$ary = holiday::callGoogle();
//		print_r($ary);

		//"2013-05-06";s:12:"振替休日"
		$b = new holiday();
		$c = $b->isHoliday('2013-05-06');
		$this->assertEqual($c, '振替休日');
		$c = $b->isHoliday('2013/05/06');
		$this->assertEqual($c, '振替休日');
		$c = $b->isHoliday('2013.05.06');
		$this->assertEqual($c, '振替休日');
		$c = $b->isHoliday('2013/5/6');
		$this->assertEqual($c, '振替休日');
		$c = $b->isHoliday('20130506');
		$this->assertEqual($c, '振替休日');
	}
}
}
}